package com.yuju.util;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 类名：GenericsUtil  <br />
 *
 * 功能：泛型 util类
 *
 * @author : xuehj <br />
 * @Date : 2017年9月14日 上午11:11:41  <br />
 * @version : 1.1 <br />
 */
public class GenericsUtil {

    private static final Logger logger = LoggerFactory.getLogger(GenericsUtil.class);

    private GenericsUtil() {
    }

    /**
     * 通过反射,获得定义Class时声明的父类的范型参数的类型.
     * 如public UserDao extends BaseDao<User>
     *
     * @param clazz The class to introspect
     * @return the first generic declaration, or <code>Object.class</code> if
     * cannot be determined
     */
    @SuppressWarnings("rawtypes")
    public static Class getSuperClassGenricType(Class clazz) {
        return getSuperClassGenricType(clazz, 0);
    }

    /**
     * 通过反射,获得定义Class时声明的父类的范型参数的类型.
     * 如public UserDao extends BaseDao<User>
     *
     * @param clazz clazz The class to introspect
     * @param index the Index of the generic ddeclaration,start from 0.
     * @return the index generic declaration, or <code>Object.class</code> if
     * cannot be determined
     */
    @SuppressWarnings("rawtypes")
    public static Class getSuperClassGenricType(Class clazz, int index) {

        Type genType = clazz.getGenericSuperclass();

        if (!(genType instanceof ParameterizedType)) {
            logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        }

        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

        if (index >= params.length || index < 0) {
            logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + params.length);
            return Object.class;
        }
        if (!(params[index] instanceof Class)) {
            logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
            return Object.class;
        }
        return (Class) params[index];
    }
}
